上一讲我们学习了如何基于 API Route 编写接口,有了接口就需要获取数据,Nuxt3 中提供的多种数据访问 API:
- $fetch;
- useAsyncData;
- useLazyAsyncData;
- useFetch;
- useLazyFetch。
# 为什么需要 $fetch?
前面说过,如果开发团队有服务端,并且接口已经开发完毕,则我们可以直接调用这些接口。但是由于我们是服务端渲染,不得不考虑接口的调用时机问题:
- 首屏渲染,调用发生在服务端;
- 客户端激活之后,调用发生在客户端。
这导致我们首先需要判断代码执行环境,其次发送请求的 API 可能不同,另外如果在客户端发送请求到其他接口服务器还会存在跨域问题,需要给项目配代理,很复杂是吧!这就是 Nuxt3 为什么替我们封装了 $fetch ,它全局可用,可以智能处理调用时机,还能统一 API,避免配置代理。
# Nuxt3 数据访问 API
上节课我们用到了$fetch,我们会像下面这样使用它:
csharp
复制代码const { data } = await $fetch('/api/hello', { query: { name: 'tom' } })
const { result } = await $fetch('/api/post', { method: 'post', body: newPost })
@前端进阶之旅: 代码已经复制到剪贴板
可以看到,$fetch 的 API 和 fetch 是一样的,实际调用的是 unjs/ofetch。它的用法符合我们之前的编码习惯,返回 Promise,然后用户负责处理后续操作。但如果要加上一些其他 loading、error 等反馈,我们通常要添加额外组件状态来实现,比较繁琐。
后来到了 hooks 时代,React 社区出现了诸如 ahooks、swr 等库,通过封装请求,暴露出 data、loading、error 等状态,然后可以在组件内直接使用,非常高效。Nuxt3 也为我们提供了四个接口,通过封装 $fetch,给用户提供响应式数据便于直接使用。下面我们一起来看一下它们的使用方式异同:
# useFetch
页面、组件或者插件中可以使用useFetch获取任意 URL 资源。useFetch是对useAsyncData和$fetch的封装,只需传入请求的 URL 或者一个请求函数即可,一些选项会自动填入,用起来最简洁,是最推荐的数据获取方式。
useFetch方法签名:
typescript
复制代码function useFetch(
url: string | Request | Ref<string | Request> | () => string | Request,
options?: UseFetchOptions<DataT>
): Promise<AsyncData<DataT>>
type AsyncData<DataT> = {
data: Ref<DataT> // 返回数据
pending: Ref<boolean> // 加载状态
refresh: (opts?: { dedupe?: boolean }) => Promise<void> // 刷新数据
execute: () => Promise<